<style>
	/*auto*/
	.ui-filelistbox { border: 1px solid #E0E0E0; font-size: 14px; color: black; position: relative; }
	.ui-filelistbox ul { list-style-type: none; width: 100%; height: 100%; overflow: auto; margin: 0; padding: 0; font-size: 12px; }
	.ui-filelistbox li { border-bottom: 1px solid #E0E0E0; padding: 0 10px; cursor: pointer; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; overflow-scrolling: touch; }
	.ui-filelistbox-dragdrop { border-color: #6290C8; }
	.ui-filelistbox-name { padding: 3px 0 0 0; display: block; margin-right: 280px; }
	.ui-filelistbox li > .fa { width: 22px; font-size: 12px; border-right: 1px solid #E0E0E0; margin-right: 7px; color: #5590CD; float: left; height: 22px; padding: 5px 0 0 0; }
	.ui-filelistbox li:hover { background-color: #F0F0F0; }
	.ui-filelistbox-selected { background-color: #FFE7A4 !important; }
	.ui-filelistbox-search-empty { height: 34px; }
	.ui-filelistbox-search { border-bottom: 1px solid #E0E0E0; height: 34px; background-color: white; position: absolute; width: 100%; box-shadow: 0 5px 10px rgba(0,0,0,0.05); }
	.ui-filelistbox-search input { width: 100%; outline: 0; background-color: white; font: normal normal 12px Arial; border: 0; margin: 0; padding: 0; }
	.ui-filelistbox-search span { float: left; width: 30px; text-align: center; height: 30px; padding: 8px 0 0 0; font-size: 12px; color: #A0A0A0; }
	.ui-filelistbox-search .fa-times { color: red; cursor: pointer; }
	.ui-filelistbox-search div { margin-left: 30px; padding: 6px 10px 0 0; }
	.ui-filelistbox-invalid { border-color: #E1A1A1; background-color: #FFF3F3 !important; }
	.ui-filelistbox-invalid .ui-filelistbox-search { border-color: #E1A1A1; }
	.ui-filelistbox.ui-disabled input { background-color: #F0F0F0; color: gray; }
	.ui-filelistbox.ui-disabled .ui-filelistbox-search { background-color: #F0F0F0; }
	.ui-filelistbox.ui-disabled ul { color: gray; overflow: hidden; }
	.ui-filelistbox.ui-disabled li:hover { background-color: white; }
	.ui-filelistbox.ui-disabled li { cursor: not-allowed; }
	.ui-filelistbox.ui-disabled .ui-filelistbox-selected { background-color: #D0D0D0 !important; }
	.ui-filelistbox-date { float: right; font-size: 11px; color: #A0A0A0; padding: 3px 5px 0 0; }
	.ui-filelistbox-dimension { float: right; font-size: 11px; color: #A0A0A0; border-left: 1px solid #E0E0E0; width: 90px; text-align: center; height: 22px; padding: 3px 0 0 0; background-color: rgba(0,0,0,0.03); }
	.ui-filelistbox-size { float: right; font-size: 11px; color: #A0A0A0; border-left: 1px solid #E0E0E0; width: 60px; text-align: right; height: 22px; padding: 3px 0 0 0; }
	.ui-filelistbox-preview { float: right; font-size: 11px; margin: 0 0 0 7px; border-left: 1px solid #E0E0E0; padding: 3px 0 0 5px; height: 22px; width: 30px; text-align: center; }
	.ui-filelistbox-pagination { height: 35px; background-color: #F5F5F5; padding: 4px 0 0 5px; box-shadow: 0 -5px 7px rgba(0,0,0,0.05); border-top: 1px solid #E0E0E0; }
	.ui-filelistbox-pagination button { width: 22px; height: 22px; border: 0; background-color: #4285F4; border-radius: 3px; outline: 0; font-size: 12px; vertical-align: middle; padding: 2px 0 0 0; margin: 3px 5px 0 0; float: left; color: white; }
	.ui-filelistbox-pagination button:hover { opacity: 0.9; }
	.ui-filelistbox-pagination button:disabled { color: silver; cursor: not-allowed; background-color: #F8F8F8 !important; }
	.ui-filelistbox-pagination div { float: left; font-size: 11px; vertical-align: middle; margin: 6px 0 0 8px; }

	@media(max-width: 767px) {
		.ui-filelistbox-date { display: none; }
		.ui-filelistbox-dimension { display: none; }
		.ui-filelistbox-size { display: none; }
	}

</style>

<div data-jc="form" data-jc-path="common.form3" class="hidden" data-jc-config="icon:folder-o;if:filebrowser;title:@(File Browser);width:800;autofocus:true">
	<div class="padding">
		<div class="m" data-jc="filelistbox" data-jc-path="filebrowser.id" data-jc-config="datasource:filebrowser.files;search:@(Search file ...);exec:filebrowser_submit;filter:filebrowser_filter"></div>
		<div class="row">
			<div class="col-xs-6">
				<a href="javascript:void(0)" data-jc="fileupload" data-jc-id="filebrowser.filename" data-jc-path="filebrowser.filename" data-jc-config="url:[url]api/upload/" class="fs12"><i class="fa fa-folder-o mr5"></i>@(Upload new file)</a>
			</div>
			<div class="col-xs-6 right">
				<a href="javascript:void(0)" class="fs12 red exec" data-exec="filebrowser_clear"><i class="fa fa-trash mr5"></i>@(Clear useless files)</a>
			</div>
		</div>
	</div>
	<div class="ui-form-buttons">
		<button name="cancel" style="width:100%">@(Cancel)</button>
	</div>
</div>

<script>
	COMPONENT('filelistbox', 'height:200', function(self, config) {

		var Eitems, datasource, filter = null;
		var skip = false;
		var psel = '.ui-filelistbox-pagination';
		var pages = self.virtualize({ prev: psel + ' button[name="prev"]', next: psel + ' button[name="next"]', info: psel + ' div' });

		self.readonly();
		self.datasource = EMPTYARRAY;
		self.template = Tangular.compile('<li data-index="{{ index }}"><a href="/download/{{ value }}" target="_blank" class="ui-filelistbox-preview"><i class="fa fa-search"></i></a><span class="ui-filelistbox-size">{{ size | filesize }}</span><span class="ui-filelistbox-dimension">{{ if width }}{{ width }}x{{ height }}{{ else }}{{ fi }}</span><span class="ui-filelistbox-date">{{ mtime | format(\'@(yyyy-MM-dd)\') }}</span>{{ if icon }}<i class="fa fa-{{ icon }}"></i>{{ fi }}<span class="ui-filelistbox-name">{{ text }}</span></li>');

		self.make = function() {

			self.aclass('ui-filelistbox');
			self.redraw();

			config.datasource && self.reconfigure('datasource:' + config.datasource);

			self.event('dragenter dragover dragexit drop dragleave', function (e) {

				e.stopPropagation();
				e.preventDefault();

				switch (e.type) {
					case 'drop':
						self.rclass('ui-filelistbox-dragdrop');
						break;
					case 'dragenter':
					case 'dragover':
						self.aclass('ui-filelistbox-dragdrop');
						return;
					case 'dragexit':
					case 'dragleave':
					default:
						self.rclass('ui-filelistbox-dragdrop');
						return;
				}

				var files = e.originalEvent.dataTransfer.files;
				SETTER('#filebrowser.filename', 'upload', files);
			});

			self.event('click', 'a', function(e) {
				e.stopPropagation();
			});

			self.event('click', 'li', function() {
				if (config.disabled)
					return;

				var index = +this.getAttribute('data-index');
				var value = self.datasource[index];

				skip = true;

				self.set(value.value);
				config.exec && EXEC(config.exec, value.value, value.text);
				self.change(true);
			});

			self.event('click', '.fa-times', function() {
				if (!config.disabled) {
					self.find('input').val('');
					self.search();
				}
			});

			self.event('click', 'button', function() {
				switch (this.name) {
					case 'prev':
						if (pages.page > 0) {
							pages.page--;
							self.paginate();
						}
						break;
					case 'next':
						pages.page++;
						self.paginate();
						break;
				}
			});

			typeof(config.search) === 'string' && self.event('keydown', 'input', function() {
				!config.disabled && setTimeout2(self.id, self.search, 500);
			});
		};

		self.configure = function(key, value, init) {

			if (key === 'filter') {
				filter = value ? GET(value) : null;
				return;
			}

			if (init)
				return;

			var redraw = false;

			switch (key) {
				case 'type':
					self.type = value;
					break;
				case 'disabled':
					self.tclass('ui-disabled', value);
					self.find('input').prop('disabled', value);
					if (value)
						self.rclass('ui-filelistbox-invalid');
					else if (config.required)
						self.state(1, 1);
					break;
				case 'required':
					!value && self.state(1, 1);
					break;
				case 'search':
					redraw = true;
				case 'height':
					Eitems.css('height', value + 'px');
					break;
				case 'datasource':
					datasource && self.unwatch(datasource, self.bind);
					self.watch(value, self.bind, true);
					datasource = value;
					break;
			}

			redraw && self.redraw();
		};

		self.search = function() {
			pages.page = 0;
			self.paginate();
		};

		self.redraw = function() {
			self.html((typeof(config.search) === 'string' ? '<div class="ui-filelistbox-search"><span><i class="fa fa-search ui-filelistbox-search-icon"></i></span><div><input type="text" placeholder="{0}" /></div></div><div><div class="ui-filelistbox-search-empty"></div>'.format(config.search) : '') + '<div><ul style="height:{0}px"></ul></div><div class="ui-filelistbox-pagination"><button name="prev" disabled="disabled"><i class="fa fa-chevron-left"></i></button><button name="next" disabled="disabled"><i class="fa fa-chevron-right"></i></button><div></div></div>'.format(config.height));
			Eitems = self.find('ul');
		};

		self.bind = function(path, value) {
			pages.page = 0;
			self.paginate();
		};

		self.paginate = function() {

			var page = pages.page;
			var search = config.search ? self.find('input').val().toSearch() : '';
			var data = self.get(config.datasource) || EMPTYARRAY;
			var take = 150;
			var skip = page * take;
			var index = 0;
			var builder = [];

			self.datasource = [];

			for (var i = 0, length = data.length; i < length; i++) {

				var item = data[i];

				if (search) {
					if (item.name.toSearch().indexOf(search) === -1)
						continue;
				}

				index++;

				if (skip > index)
					continue;

				if (take-- <= 0)
					break;

				var obj = { text: item.name, value: item.id, index: self.datasource.length, icon: item.type.substring(0, 5) === 'image' ? 'picture-o' : 'file-o', size: item.size, width: item.width, height: item.height, mtime: item.mtime };
				self.datasource.push(obj);
				builder.push(self.template(obj));
			}

			pages.prev.disable(page === 0);
			pages.next.disable(self.datasource.length === 0);
			pages.info.html('<b>{0}</b> / @(page)'.format((page + 1)));
			Eitems.empty().append(builder.join(''));
		};

		self.released = function(is) {
			is && Eitems.empty();
		};

		self.setter = function(value) {

			var selected = {};
			var builder = [];

			var ds = self.datasource;
			var dsl = ds.length;

			if (value != null) {
				if (config.multiple) {
					for (var i = 0, length = value.length; i < length; i++) {
						for (var j = 0; j < dsl; j++) {
							if (ds[j].value === value[i])
								selected[j] = true;
						}
					}
				} else {
					for (var j = 0; j < dsl; j++) {
						if (ds[j].value === value)
							selected[j] = true;
					}
				}
			}

			var first;

			Eitems.find('li').each(function() {
				var el = $(this);
				var index = +el.attrd('index');
				var is = selected[index] !== undefined;
				el.tclass('ui-filelistbox-selected', is);
			});

			self.search();
		};

		self.state = function(type) {
			if (!type)
				return;
			var invalid = config.required ? self.isInvalid() : false;
			if (invalid === self.$oldstate)
				return;
			self.$oldstate = invalid;
			self.tclass('ui-filelistbox-invalid', invalid);
		};
	});

	WATCH('filebrowser.filename', function(path, value) {

		if (!value || !value.length)
			return;

		var files = filebrowser.files;
		files.push.apply(files, value);
		files.quicksort('ctime', false);

		var obj = filebrowser;
		var url = value[0].download;
		var type = typeof(obj.target);
		if (type === 'string') {
			SET(obj.target, url);
			CHANGE(obj.target, true);
		} else if (type === 'function') {
			obj.target(url, value[0].name);
		} else {
			if (/\.(jpg|png|gif|svg|jpeg)$/.test(url))
				$(obj.target).attr('src', url);
			else {
				SETTER('snackbar', 'warning', '@(You need to choose an image.)');
				return;
			}
		}

		SET('common.form3', '');
	});

	function filebrowser_filter(item) {
		if (filebrowser.type)
			return filebrowser.type.test(item.type) ? true : false;
		else
			return true;
	}

	function filebrowser_clear() {
		SETTER('confirm', 'confirm', '@(Are you sure you want to remove all useless files?)', ['"trash"@(Remove)', '@(No)'], function(index) {
			if (index)
				return;
			SETTER('loading', 'show');
			AJAX('GET [url]api/files/clear/', function() {
				SETTER('loading', 'hide', 1000);
				SETTER('snackbar', 'success', '@(Cleaning of useless files has been started.)');
			});
		});
	}

	function filebrowser_refresh() {
		filebrowser.clear = true;
		refresh_filebrowser(filebrowser.target, filebrowser.type);
	}

	function filebrowser_submit(val, text) {
		var obj = filebrowser;
		var url = '/download/' + obj.id;
		var type = typeof(obj.target);
		if (type === 'string') {
			SET(obj.target, url);
			CHANGE(obj.target, true);
		} else if (type === 'function') {
			obj.target(url, text);
		} else {
			if (/\.(jpg|png|gif|svg|jpeg)$/.test(url))
				$(obj.target).attr('src', url);
			else {
				SETTER('snackbar', 'warning', '@(You need to choose an image.)');
				return;
			}
		}
		SET('common.form3', '');
	}

</script>